<template>
	<view class="wflow-form">
		<uni-forms ref="wflowForm"  class="wflow-form" :rules="rules" :modelValue="_value" >
			<template v-for="item in formFields" :key="item.id">
			<uni-forms-item :class="[
				item?.name === 'TableList' ? 'w-form-item-table' : 'w-form-item',
				item?.perm === 'R' ? 'w-form-item-r' : ''
			]"
				 style="height:auto;margin:0 ;line-height: 20rpx;"
				v-show="showItem(item, _value[item.id])" :name="item.id"  :required="item.props.required">
				<template v-slot:label v-if="item.name !== 'Applicant'">
					<view class="w-form-title">
						<text style="color: #CE5266;" v-if="item.props.required && item.perm === 'E'">* </text>
						<text style="line-height: 30rpx">{{ $t(item.title) }}</text>
					</view>
				</template>
				<w-form-item :id="item.id" :type="item.name" v-model="_value[item.id]" :form-props="item.props"
					:readonly="item.perm !== 'E'" :formData="_value" />
			</uni-forms-item>
			</template>
		</uni-forms>
	</view>

</template>

<script>
import {
	showItem
} from '@/utils/tool.js'
import WFormItem from './WFormItem.vue'
import {
	CompareFuncs
} from "./form/compare/CompareOptions.js";
import { computed } from 'vue';
// #ifndef H5
import {
	Function
} from "eval5";
// #endif
//import FormComponents from '@/components/form/ComponentsExport.js'

export default {
	name: 'FormRender',
	options: {
		styleIsolation: 'shared'
	},
	components: {
		WFormItem
	},
	props: {
		modelValue: { //表单双向绑定的值
			type: Object,
			default: () => {
				return {}
			}
		},
		config: { //表单联动相关配置
			type: Object,
			default: () => {
				return {
					ruleType: "SIMPLE",
					rules: [],
				}
			}
		},
		jsonConf: { //表单json配置，用来渲染表单
			type: Array,
			default: () => {
				return []
			}
		}
	},
	computed: {
		_value: {
			get() {
				return this.modelValue
			},
			set(val) {
				emit('update:modelValue', val)
			}
		},
		formFields() {
			const fields = []
			this.jsonConf.forEach(field => this.loadInnerField(field, fields))
			return fields
		},
		formItemMap() {
			const map = new Map()
			this.loadFormItemMap(this.jsonConf, map)
			return map
		}
	},
	data() {
		return {
			validFuncs: {}, //自定义组件校验函数
			//缓存下原始权限设置
			formPermHis: {},
			compareFunc: {},
			//缓存旧值
			oldFormData: {},
			//缓存所有用到的条件字段
			conditionFields: new Set(),
			execute: null,
			rules: {}
		}
	},
	provide() {
		return {
			validFuncs: computed(() => {
				return this.validFuncs
			})
		}
	},
	methods: {
		showItem,
		reloadRules() {
			this.rules = {}
			this.formFields.forEach(v => {
				this.rules[v.id] = { rules: [] }
				if (v.props.required && v.perm === 'E') {
					this.rules[v.id].rules.push({
						required: true,
						errorMessage: '请填写' + this.$t(v.title),
					})
				}
				if (this.validFuncs[v.id]) {
					this.rules[v.id].rules.push({
						errorMessage: '请完成数据项',
						validateFunction: this.validFuncs[v.id]
					})
				}
			})
			if (this.$refs['wflowForm']) {
				console.log('重置规则', this.rules)
				this.$refs['wflowForm'].setRules(this.rules)
			}
		},

		loadInnerField(field, items) {
			if (field.name === 'SpanLayout') {
				field.props.items.forEach(f => this.loadInnerField(f, items))
			} else {
				items.push(field)
			}
		},
		validate(call) {
			this.reloadRules()
			setTimeout(() => {
				this.$refs['wflowForm'].validate().then(res => {
					call(true)
					console.log('表单数据信息：', res);
				}).catch(err => {
					if (Array.isArray(err) && err.filter(e => e.key === 'invalid').length === err
						.length) {
						call(true)
					} else {
						call(false)
						console.log('表单错误信息：', err);
					}
				})
			}, 200)

		},
		loadFormItemMap(forms, map) {
			forms.forEach(item => {
				if (item.name === 'TableList') {
					map.set(item.id, item)
					this.loadFormItemMap(item.props.columns, map)
				} else if (item.name === 'SpanLayout') {
					this.loadFormItemMap(item.props.items, map)
				} else {
					map.set(item.id, item)
				}
			})
		},
		loadFormConfig(forms, rules) {
			forms.forEach((item) => {
				if (item.name === 'SpanLayout') {
					this.loadFormConfig(item.props.items, rules)
				} else {
					this._value[item.id] = this.modelValue[item.id]
					if (item.props.required && this.showItem(item) && item.name !== 'OuterForm') {
						let a = ''
						if (item.name === 'SelectPlus') {
							a = typeof this._value[item.id] == 'string' ? a : 'Array'
							item.valueType = a
						}
						rules[item.id] = [
							{
								type: item.name === 'Selector' ? 'string' : ValueType.getValidType(item.valueType),
								required: true,
								message: `请完成${item.title}`,
								trigger: 'blur',
							},
						]
					}
				}
				// console.log("rules",rules)
			})
		},
		//解析表单联动规则
		parserRule(cdRule) {
			const condition = cdRule.condition
			//在这里可以实现一个算法，按条件层级去解析，不需要解析所有条件，先不实现
			if (cdRule.children.length > 0) {
				for (let i = 0; i < cdRule.children.length; i++) {
					const result = this.parserRule(cdRule.children[i])
					if (cdRule.logic) {
						//如果是且关系，有一个为假就是假
						if (!result) {
							return false
						}
					} else {
						//如果是或关系，有一个为真就是真
						if (result) {
							return true
						}
					}
				}
				//遍历完了返回最终结果
				return cdRule.logic
			} else {
				//解析条件
				try {
					return this.compare(condition)
				} catch (e) {
					return false
				}
			}
		},
		async doActions(actions) {
			(actions || []).forEach(action => {
				//执行预设的动作
				switch (action.type) {
					case 'SHOW':
						action.targets.forEach(tg => this.showField(tg));
						break;
					case 'HIDE':
						action.targets.forEach(tg => this.hideField(tg));
						break;
					case 'DISABLE':
						action.targets.forEach(tg => this.disableField(tg));
						break;
					case 'UPDATE':
						action.targets.forEach(tg => this.updateField(tg, action.value));
						break;
					case 'ENABLE':
						action.targets.forEach(tg => this.enableField(tg, action.value));
						break;
				}
			})
		},
		analyseFormRule() {
			if (this.config.ruleType === 'SIMPLE') {
				this.analyseRules()
			} else {
				this.analyseJsRules()
			}
		},
		async analyseJsRules() {
			// #ifndef MP-WEIXIN
			if (!(this.execute instanceof Function)) {
				this.execute = new Function(`${this.config.ruleJs || 'function doChange(){}'}\r\n return doChange`)
				this.execute = this.execute()
			}
			this.execute(this._value, this.formItemMap)
			// #endif

		},
		async analyseRules() {
			(this.config.rules || []).forEach((rule, i) => {
				//解析表单联动条件
				const result = this.parserRule(rule.condition)
				console.log(`解析规则 ${(i + 1)}: ${result}`)
				this.doActions(result ? rule.action.with : rule.action.other)
			})
		},
		compare(condition) {
			//要判断组件类型，再取其值
			const source = this._value[condition.field]
			//动态调用函数
			let compareType = null
			switch (condition.fieldType) {
				case 'AmountInput':
				case 'NumberInput':
				case 'Score':
				case 'CalcFormula':
					compareType = 'numCompare';
					break;
				case 'TextInput':
				case 'TextareaInput':
				case 'SelectInput':
				case 'Location':
				case 'Provinces':
				case 'Selector':
				case 'TextSelector':
					compareType = 'strCompare'
					break;
				case 'MultipleSelect':
					compareType = 'strArrCompare';
					break;
				case 'DateTime':
					compareType = 'timeCompare';
					break;
				case 'DateTimeRange':
					compareType = 'timeArrCompare';
					break;
				case 'DeptPicker':
				case 'UserPicker':
					compareType = 'orgCompare';
					break;
			}
			return CompareFuncs[compareType][condition.compare](source,
				condition.fixed ? condition.compareVal :
					this._value[condition.compareVal[0]])
			},
			isRequired(item) {
				return this.rules[item.id] !== undefined
			},
			hideField(id) {
				const field = this.formItemMap.get(id)
				if (field) {
					field.perm = 'H'
				}
			},
			showField(id) {
				const field = this.formItemMap.get(id)
				if (field) {
					field.perm = this.formPermHis[id] || 'E'
				}
			},
			disableField(id) {
				const field = this.formItemMap.get(id)
				if (field) {
					field.perm = 'R'
				}
			},
			enableField(id) {
				const field = this.formItemMap.get(id)
				if (field) {
					field.perm = 'E'
				}
			},
			updateField(id, val) {
				const field = this.formItemMap.get(id)
				if (field) {
					this._value[id] = val
				}
			},
			doRule(){
				if (this.config) {
					if (Object.keys(this.formPermHis).length === 0) {
						this.formItemMap.forEach(item => {
							this.formPermHis[item.id] = item.perm
						})
					}
					this.analyseFormRule()
				}
			}
		},
		watch: {
			config: {
				deep: true,
				handler() {
					this.doRule()
				}
			},
			modelValue: {
				deep: true,
				immediate: true,
				handler() {
					this.doRule()
				}
			}
		},
		emits: ['update:modelValue']
	}
</script>

<style lang="less" scoped>
.wflow-form {
	margin-bottom: 100rpx !important;

}

.w-form-item:first-of-type {
	padding-top: 16rpx;
	/* 这里的样式将应用于每个父元素下的第一个 .w-form-item */
}

.w-form-item {
	// padding: 0 16rpx 0 16rpx;
	padding: 0rpx 16rpx 32rpx 16rpx;

	background-color: white;

	.uni-forms-item__error {
		padding-top: 0 !important;
	}

	.uni-easyinput__content-input {
		height: 60rpx;
	}

	.w-form-title {
		width: 120rpx;
		display: flex;
		align-items: center;
		text-align: right;
		// padding: 13rpx 0;
		padding-right: 13rpx;
		font-size: 24rpx !important;
		justify-content: right;
	}
}

.w-form-item-table {
	display: flex;
	flex-direction: column !important;
	padding: 0rpx 16rpx 32rpx 16rpx;

	background-color: white;

	.uni-forms-item__error {
		padding-top: 0 !important;
	}

	.uni-easyinput__content-input {
		height: 60rpx;
	}

	.w-form-title {
		width: 100%;
		height: 60rpx;
		display: flex;
		align-items: center;
		background-color: #ccc;
		text-align: center;
		// padding: 13rpx 0;
		// padding-right: 13rpx;
		font-size: 24rpx !important;
		justify-content: center;
		margin-bottom: 16rpx;


	}
}
</style>
